{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "authorship_tag": "ABX9TyMY0NHCY3ctYgA5Nmkt6RDI",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/LuisGSVasconcelos/Redes_Neurais_PPGEQ_UFCG/blob/main/Victor/2.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Python Basics"
      ],
      "metadata": {
        "id": "VLiHtdH3gnUa"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# basic data types\n",
        "i = 2 # integer; type(i) = int\n",
        "f = 1.2 # floating-point number; type(f) = float\n",
        "s = 'two' # string; type(s) = str\n",
        "b = True # boolean; type(b) = bool\n",
        "\n",
        "# basic operations\n",
        "print(i+2) # displays 4\n",
        "print(f*2) # displays 2.4\n",
        "print(not b)# displays False"
      ],
      "metadata": {
        "id": "P6z8mIjdgpNF",
        "outputId": "66767289-927c-451d-ddd9-2c7bba8f2a5e",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "4\n",
            "2.4\n",
            "False\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# ordered sequences\n",
        "# different ways of creating lists\n",
        "list1 = [2,4,6]\n",
        "list2 = ['air',3,1,5]\n",
        "list3 = list(range(4)) # equals [0,1,2,3]; range function returns a sequence of numbers starting from 0 (default) with increments of 1 (default)\n",
        "list3.append(8) # returns [0,1,2,3,8];  append function adds new items to existing list\n",
        "print(list3)\n",
        "\n",
        "list4 = list1 + list2 # equals [2,4,6,'air',3,1,5]\n",
        "list5 = [list2, list3] # nested list [['air', 3, 1, 5], [0, 1, 2, 3,8]]\n",
        "print(list5)\n",
        "\n",
        "# creating tuples\n",
        "tuple1 = (0,1,'two')\n",
        "tuple2 = (list1, list2) # equals ([2, 4, 6, 8], ['air', 3, 1, 5])\n",
        "print(tuple2)"
      ],
      "metadata": {
        "id": "5_xuux3ogq1F",
        "outputId": "a623abec-9fa2-42c7-e5d1-311f7d89a5bf",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "[0, 1, 2, 3, 8]\n",
            "[['air', 3, 1, 5], [0, 1, 2, 3, 8]]\n",
            "([2, 4, 6], ['air', 3, 1, 5])\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# list comprehension\n",
        "# return powers of list items\n",
        "newList1 = [item**2 for item in list3] # equals [0,1,4,9, 64]\n",
        "# nested list comprehension\n",
        "newList2 = [item2**2 for item2 in [item**2 for item in list3]] # equals [0,1,16,81, 4096]\n",
        "print(newList2)"
      ],
      "metadata": {
        "id": "lT0hHcU0gseg",
        "outputId": "477d4692-941e-4d16-c29d-bcd346304a8c",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "[0, 1, 16, 81, 4096]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Indexing and slicing sequences\n",
        "# working with single item using positive or negative indexes\n",
        "print(list1[0]) # displays 2, the 1st item in list1\n",
        "list2[1] = 1 # list2 becomes ['air',1,1,5]\n",
        "print(list2[-2]) # displays 1, the 2nd last element in list2\n",
        "\n",
        "# accessing multiple items through slicing\n",
        "# Syntax: givenList[start,stop,step]; if unspecified, start=0, stop=list length, step=1\n",
        "print(list4[0:3]) # displays [2,4,6], the 1st, 2nd, 3rd items; note that index 3 item is excluded\n",
        "print(list4[:3]) # same as above\n",
        "print(list4[4:len(list4)]) # displays [3,1,5]; len() function returns the number of items in list\n",
        "print(list4[4:]) # same as above\n",
        "print(list4[::3]) # displays [2, 'air', 5]\n",
        "print(list4[::-1]) # displays list 4 backwards [5, 1, 3, 'air', 6, 4, 2]\n",
        "list4[2:4] = [0,0,0] # list 4 becomes [2, 4, 0, 0, 0, 3, 1, 5]"
      ],
      "metadata": {
        "id": "z0BYaT9TguKr",
        "outputId": "066163bb-a033-4467-8fda-e3b9444a0fa8",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "2\n",
            "1\n",
            "[2, 4, 6]\n",
            "[2, 4, 6]\n",
            "[3, 1, 5]\n",
            "[3, 1, 5]\n",
            "[2, 'air', 5]\n",
            "[5, 1, 3, 'air', 6, 4, 2]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Execution control statements\n",
        "# conditional execution\n",
        "# selectively execute code based on condition\n",
        "if list1[0] > 0:\n",
        "    list1[0] = 'positive'\n",
        "else:\n",
        "    list1[0] = 'negative'\n",
        "\n",
        "# loop execution\n",
        "# code below computes sum of squares of numbers in list 3\n",
        "sum_of_squares = 0\n",
        "for i in range(len(list3)):\n",
        "    sum_of_squares += list3[i]**2\n",
        "\n",
        "print(sum_of_squares) # displays 78"
      ],
      "metadata": {
        "id": "Gxv2LQBsgwRu",
        "outputId": "d24d1970-1d76-4a9f-f62d-e5ca9b7fd06d",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "78\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# custom functions\n",
        "# define function instructions\n",
        "def sumSquares(givenList):\n",
        "    sum_of_squares = 0\n",
        "    for i in range(len(givenList)):\n",
        "        sum_of_squares += givenList[i]**2\n",
        "\n",
        "    return sum_of_squares\n",
        "\n",
        "# call/re-use the custom function multiple times\n",
        "print(sumSquares(list3)) # displays 78\n",
        "print(sumSquares(list4)) # displays 55"
      ],
      "metadata": {
        "id": "qjbe4D9qgx3P",
        "outputId": "9e8e4cb4-5fb5-4148-90c9-25bda9c84aa1",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "78\n",
            "55\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## NumPy Basics"
      ],
      "metadata": {
        "id": "tbdlZE-ShGs_"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# create a 2D array\n",
        "import numpy as np\n",
        "\n",
        "arr2D = np.array([[1,4,6],[2,5,7]])\n",
        "\n",
        "# getting information about arr2D\n",
        "print(arr2D.size) # returns 6, the no. of items\n",
        "print(arr2D.ndim) # returns 2, the no. of dimensions\n",
        "print(arr2D.shape) # returns tuple(2,3) corresponding to 2 rows & 3 columns\n",
        "\n",
        "# create a 1D array\n",
        "arr1D = np.array([1,4,6])\n",
        "\n",
        "# getting information about arr1D\n",
        "print(arr1D.size) # returns 3, the no. of items\n",
        "print(arr1D.ndim) # returns 1, the no. of dimensions\n",
        "print(arr1D.shape) # returns tuple(3,) corresponding to 3 items"
      ],
      "metadata": {
        "id": "yg9JmW68hIGy",
        "outputId": "03aa5cba-f7d2-43cc-ad2a-a6e5794e273e",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "6\n",
            "2\n",
            "(2, 3)\n",
            "3\n",
            "1\n",
            "(3,)\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# creating numpy arrays\n",
        "# creating sequence of numbers\n",
        "arr1 = np.arange(3, 6) # same as Python range function; results in array([3,4,5])\n",
        "arr2 = np.arange(3, 9, 2) # the 3rd argument defines the step size; results in array([3,5,7])\n",
        "arr3 = np.linspace(1,7,3) # creates evenly spaced 3 values from 1 to 7; results in array([1,4,7])\n",
        "\n",
        "# creating special arrays\n",
        "arr4 = np.ones((2,1)) # array of shape (2,1) with all items as 1\n",
        "arr5 = np.zeros((2,2)) # all items as zero; often used as placeholder array at beginning of script\n",
        "arr6 = np.eye(2) # diagonal items as 1\n",
        "\n",
        "# adding axis to existing arrays (e.g., converting 1D array to 2D array)\n",
        "print(arr1[:, np.newaxis])\n",
        "arr7 = arr1[:, None] # same as above\n",
        "\n",
        "# combining / stacking arrays\n",
        "print(np.hstack((arr1, arr2))) # horizontally stacks passed arrays\n",
        "print(np.vstack((arr1, arr2))) # vertically stacks passed arrays\n",
        "print(np.hstack((arr5,arr4))) # array 4 added as a column into arr5\n",
        "print(np.vstack((arr5,arr6))) # rows of array 6 added onto arr5"
      ],
      "metadata": {
        "id": "eZIH1GbPhpIe",
        "outputId": "0a9c5f2a-ad56-4605-843b-ef56b6a9e02e",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "[[3]\n",
            " [4]\n",
            " [5]]\n",
            "[3 4 5 3 5 7]\n",
            "[[3 4 5]\n",
            " [3 5 7]]\n",
            "[[0. 0. 1.]\n",
            " [0. 0. 1.]]\n",
            "[[0. 0.]\n",
            " [0. 0.]\n",
            " [1. 0.]\n",
            " [0. 1.]]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# basic numpy functions\n",
        "print(arr2D.sum(axis=0))\n",
        "print(arr2D.sum(axis=1))"
      ],
      "metadata": {
        "id": "ppaWqgxUhpga",
        "outputId": "0c83a716-b28b-4e23-a6af-539dc52ebb06",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "[ 3  9 13]\n",
            "[11 14]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# indexing arrays\n",
        "# accessing individual items\n",
        "print(arr2D[1,2]) # returns 7\n",
        "\n",
        "# slicing\n",
        "arr8 = np.arange(10).reshape((2,5)) # rearrange the 1D array into shape (2,5)\n",
        "print((arr8[0:1,1:3]))\n",
        "print((arr8[0,1:3])) # note that a 1D array is returned here instead of the 2D array above\n",
        "\n",
        "# accessing entire row or column\n",
        "print(arr8[1]) # returns 2nd row as array([5,6,7,8,9]); same as arr8[1,:]\n",
        "print(arr8[:, 4]) # returns items of 5th column as a 1D array\n",
        "\n",
        "# extract a subarray from arr8 and modify it\n",
        "arr8_sub = arr8[:, :2] # columns 0 and 1 from all rows\n",
        "arr8_sub[1, 1] = 1000\n",
        "print(arr8) # arr8 gets modified as well!!\n",
        "\n",
        "# use copy method for a separate copy\n",
        "arr8 = np.arange(10).reshape((2,5))\n",
        "arr8_sub2 = arr8[:, :2].copy()\n",
        "arr8_sub2[1, 1] = 100\n",
        "print(arr8)\n",
        "\n",
        "# Fancy indexing\n",
        "# combination of simple and fancy indexing\n",
        "arr8_sub3 = arr8[:, [0, 1]] # note how columns are indexed via a list\n",
        "arr8_sub3[1, 1] = 100 # arr8_sub3 becomes same as arr8_sub2 but arr8 is not modified here\n",
        "print(arr8)\n",
        "\n",
        "# use boolean mask to select subarray\n",
        "arr8_sub4 = arr8[arr8 > 5] # returns array([6,7,8,9]), i.e., all values > 5\n",
        "arr8_sub4[0] = 0 # again, arr8 is not affected\n",
        "print(arr8)"
      ],
      "metadata": {
        "id": "NjdCd2TchrKw",
        "outputId": "3295711b-bf4a-4b12-f177-b3233186e8d8",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "7\n",
            "[[1 2]]\n",
            "[1 2]\n",
            "[5 6 7 8 9]\n",
            "[4 9]\n",
            "[[   0    1    2    3    4]\n",
            " [   5 1000    7    8    9]]\n",
            "[[0 1 2 3 4]\n",
            " [5 6 7 8 9]]\n",
            "[[0 1 2 3 4]\n",
            " [5 6 7 8 9]]\n",
            "[[0 1 2 3 4]\n",
            " [5 6 7 8 9]]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# vectorized operations\n",
        "vec1 = np.array([1,2,3,4])\n",
        "vec2 = np.array([5,6,7,8])\n",
        "vec_sum = vec1 + vec2 # returns array([6,8,10,12]); no need to loop through index 0 to 3\n",
        "\n",
        "# slightly more complex operation (computing distance between vectors)\n",
        "vec_distance = np.sqrt(np.sum((vec1 - vec2)**2)) # vec_distance = 8.0\n",
        "print(vec_distance)"
      ],
      "metadata": {
        "id": "1LSS8uK_htA9",
        "outputId": "e152f7ae-5e92-4ec2-e4bb-c18e7b1bddb2",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "8.0\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Pandas Basics"
      ],
      "metadata": {
        "id": "xMbO0wFjiiss"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# create a series (1D structure)\n",
        "import pandas as pd\n",
        "\n",
        "data = [10,8,6]\n",
        "s = pd.Series(data) # can pass numpy array as well\n",
        "print(s)\n",
        "\n",
        "# create a dataframe\n",
        "data = [[1,10],[1,8],[1,6]]\n",
        "df = pd.DataFrame(data, columns=['id', 'value'])\n",
        "print(df)\n",
        "\n",
        "# dataframe from series\n",
        "s2 = pd.Series([1,1,1])\n",
        "df = pd.DataFrame({'id':s2, 'value':s})\n",
        "print(df) # same as above"
      ],
      "metadata": {
        "id": "XfhA1eFzij71",
        "outputId": "aae2d2fb-02dc-4d97-ca90-ca1db23f3615",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "0    10\n",
            "1     8\n",
            "2     6\n",
            "dtype: int64\n",
            "   id  value\n",
            "0   1     10\n",
            "1   1      8\n",
            "2   1      6\n",
            "   id  value\n",
            "0   1     10\n",
            "1   1      8\n",
            "2   1      6\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# data access\n",
        "# column(s) selection\n",
        "print(df['id']) # returns column 'id' as a series\n",
        "print(df.id) # same as above\n",
        "print(df[['id']]) # returns specified columns in the list as a dataframe\n",
        "\n",
        "# row selection\n",
        "df.index = [100, 101, 102] # changing row indices from [0,1,2] to [100,101,102]\n",
        "print(df)\n",
        "print(df.loc[101]) # returns 2nd row as a series; can provide a list for multiple rows selection\n",
        "print(df.iloc[1]) # integer location-based selection; same result as above\n",
        "\n",
        "# individual item selection\n",
        "print(df.loc[101, 'value']) # returns 8\n",
        "print(df.iloc[1, 1]) # same as above"
      ],
      "metadata": {
        "id": "Ijc6gqHQinJe",
        "outputId": "07b30a0c-55cd-4659-9053-017cee178968",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 13,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "0    1\n",
            "1    1\n",
            "2    1\n",
            "Name: id, dtype: int64\n",
            "0    1\n",
            "1    1\n",
            "2    1\n",
            "Name: id, dtype: int64\n",
            "   id\n",
            "0   1\n",
            "1   1\n",
            "2   1\n",
            "     id  value\n",
            "100   1     10\n",
            "101   1      8\n",
            "102   1      6\n",
            "id       1\n",
            "value    8\n",
            "Name: 101, dtype: int64\n",
            "id       1\n",
            "value    8\n",
            "Name: 101, dtype: int64\n",
            "8\n",
            "8\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# data aggregation exanple\n",
        "# create another dataframe using df\n",
        "df2 = df.copy()\n",
        "df2.id = 2 # make all items in column 'id' as 2\n",
        "df2.value *= 4 # multiply all items in column 'value' by 4\n",
        "print(df2)\n",
        "\n",
        "# combine df and df2\n",
        "df3 = pd.concat([df, df2]) # a new object is retuned unlike Python’s append function\n",
        "print(df3)\n",
        "\n",
        "# id-based mean values computation\n",
        "print(df3.groupby('id').mean()) # returns a dataframe"
      ],
      "metadata": {
        "id": "d4-Iv1pViomI",
        "outputId": "c2212fc3-1a9d-4e42-ac4f-28a73dfc1e23",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 15,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "     id  value\n",
            "100   2     40\n",
            "101   2     32\n",
            "102   2     24\n",
            "     id  value\n",
            "100   1     10\n",
            "101   1      8\n",
            "102   1      6\n",
            "100   2     40\n",
            "101   2     32\n",
            "102   2     24\n",
            "    value\n",
            "id       \n",
            "1     8.0\n",
            "2    32.0\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# file I/O\n",
        "# reading from excel and csv files\n",
        "dataset1 = pd.read_excel('filename.xlsx') # several parameter  options are available to customize what data is read\n",
        "dataset2 = pd.read_csv('filename.xlsx')"
      ],
      "metadata": {
        "id": "vCdezVEPiqpf"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Typical ML Script"
      ],
      "metadata": {
        "id": "rF6eYdjPdEQr"
      }
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "KnD7FC1xkRWM"
      },
      "outputs": [],
      "source": [
        "# import libraries\n",
        "import numpy as np\n",
        "from sklearn.preprocessing import PolynomialFeatures\n",
        "from sklearn.preprocessing import StandardScaler\n",
        "from sklearn.linear_model import LinearRegression\n",
        "from sklearn.metrics import r2_score\n",
        "import matplotlib.pyplot as plt"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# read data\n",
        "data = np.loadtxt('quadratic_raw_data.csv', delimiter=',')\n",
        "x = data[:,0:1]; y = data[:,1:] # equivalent to y = data[:,1,None] which returns 2D array"
      ],
      "metadata": {
        "id": "0Tgvydtk49T9"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "data"
      ],
      "metadata": {
        "id": "4ZRVQfGO49me",
        "outputId": "02b0116e-8b22-4b3d-b07b-96d1cba04e15",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[-5.  , 19.  ],\n",
              "       [-4.4 , 18.  ],\n",
              "       [-4.35, 17.8 ],\n",
              "       [-4.1 , 16.  ],\n",
              "       [-4.05, 12.2 ],\n",
              "       [-4.  , 12.  ],\n",
              "       [-3.8 ,  7.  ],\n",
              "       [-3.7 ,  6.  ],\n",
              "       [-3.5 ,  5.5 ],\n",
              "       [-3.  ,  6.5 ],\n",
              "       [-2.9 ,  6.48],\n",
              "       [-2.8 ,  6.45],\n",
              "       [-2.  ,  2.5 ],\n",
              "       [-1.95,  2.45],\n",
              "       [-1.35,  0.  ],\n",
              "       [-1.3 , -0.25],\n",
              "       [-1.15, -3.  ],\n",
              "       [ 0.  , -1.  ],\n",
              "       [ 0.2 , -0.1 ],\n",
              "       [ 0.3 , -0.12],\n",
              "       [ 0.5 , -0.11],\n",
              "       [ 1.2 , -2.  ],\n",
              "       [ 1.7 ,  1.  ],\n",
              "       [ 1.8 ,  1.4 ],\n",
              "       [ 1.9 ,  1.45]])"
            ]
          },
          "metadata": {},
          "execution_count": 3
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "x"
      ],
      "metadata": {
        "id": "CZgB6Ba04-u5",
        "outputId": "c9d4fbf6-394c-4ee3-8581-c8853bd99ee0",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[-5.  ],\n",
              "       [-4.4 ],\n",
              "       [-4.35],\n",
              "       [-4.1 ],\n",
              "       [-4.05],\n",
              "       [-4.  ],\n",
              "       [-3.8 ],\n",
              "       [-3.7 ],\n",
              "       [-3.5 ],\n",
              "       [-3.  ],\n",
              "       [-2.9 ],\n",
              "       [-2.8 ],\n",
              "       [-2.  ],\n",
              "       [-1.95],\n",
              "       [-1.35],\n",
              "       [-1.3 ],\n",
              "       [-1.15],\n",
              "       [ 0.  ],\n",
              "       [ 0.2 ],\n",
              "       [ 0.3 ],\n",
              "       [ 0.5 ],\n",
              "       [ 1.2 ],\n",
              "       [ 1.7 ],\n",
              "       [ 1.8 ],\n",
              "       [ 1.9 ]])"
            ]
          },
          "metadata": {},
          "execution_count": 4
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Pre-process / Feature engineering\n",
        "poly = PolynomialFeatures(degree=2, include_bias=False)\n",
        "X_poly = poly.fit_transform(x) # X_poly: 1st column is x, 2nd column is x^2"
      ],
      "metadata": {
        "id": "gOQD51Hf5A5A"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# scale model input variables\n",
        "scaler = StandardScaler()\n",
        "X_scaled = scaler.fit_transform(X_poly)"
      ],
      "metadata": {
        "id": "UJIpmKmR5BSj"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# fit linear model & predict\n",
        "model = LinearRegression()\n",
        "model.fit(X_poly, y)\n",
        "y_predicted = model.predict(X_poly)"
      ],
      "metadata": {
        "id": "YajnIQ2l5Cnm"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Assess model accuracy\n",
        "print('Fit accuracy = ', r2_score(y, y_predicted))\n",
        "\n",
        "# plot predictions\n",
        "plt.figure(figsize=(8, 5))\n",
        "plt.plot(x, y, 'o', label='raw data')\n",
        "plt.plot(x, y_predicted, label='quadratic fit')\n",
        "plt.legend()\n",
        "plt.xlabel('x'), plt.ylabel('y')\n",
        "plt.show()"
      ],
      "metadata": {
        "id": "ZXpGzROz5D1C",
        "outputId": "c6b2a7bd-1a3a-480d-886e-a6fdf1fa6ebd",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 482
        }
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Fit accuracy =  0.9161437726284858\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 800x500 with 1 Axes>"
            ],
            "image/png": "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ffv2+c77888/uf3222nQoAHBwcHUr18fgH379p33z3Po0CFGjBhB48aNsdvtBAcHc/LkyQu+zp2ZWlxdLhejR49m/vz5LFu2LG+ORq527drh6+vL0qVL847t2LGDffv20blz50Lf09/fn+Dg4Hy3Cnf9qxAQAom/w89vVPzni4iIeKCO0aFE2QMoas8tCxBlD6BjdGi5fH7VqlXzPd6zZw/9+vXj8ssv54svvmDDhg1MmzYNMC7eAmjZsiWhoaGsWLEiX3FdsWIF69evJysriyuvvPKicsXExJCUlMR7773HunXrWLduXb4MRRk6dCibNm3ijTfeYPXq1WzatImwsLALvs6dmVpcR40axezZs/nkk08ICgoiMTGRxMRETp8+DYDdbmf48OGMHTuWH3/8kQ0bNnDXXXfRuXNn911RACCoJvR9ybi/4iU4vN3cPCIiIh7AZrUwPqY5QIHymvt4fExzbNaK2U52w4YNOJ1OJk+ezBVXXMGll17KwYMH8+eyWOjatSsLFy5k69atdOnShcsvv5yMjAzeeecd2rdvX6AQ57Lb7URFReUVUYDs7Gw2bNiQ9/jYsWPs2LGDp59+mmuuuYZmzZpx/PjxfO+Tu/qBw+HId/znn3/mwQcf5Prrr+eyyy7D39+fo0ePXtR3YjZTi+v06dNJTk6mR48eREVF5d0+++yzvHNef/11+vXrx0033US3bt2IjIzMm3Ts1i7/BzS+DhyZ8NVocDou/BoREZFKrk+LKKbf2ZZIe/7pAJH2gApbCitXo0aNyMrK4s033+Svv/5i1qxZeRdtna1Hjx58+umntG7dmmrVqmG1WunWrRsff/zxeee3Ajz00ENMmjSJBQsWsH37du6///58UySrV69OWFgY7777Lrt27WLZsmWMHTs233tERERQpUoVYmNjOXToUN4qTY0bN2bWrFn88ccfrFu3jkGDBlGlSpWL/2JMZPpUgcJuw4YNyzsnICCAadOmkZSURFpaGl9++WWR81vdisUC/V4HvyDYvx7WFfyLLiIiIgX1aRHFqieu5tMRV/DGba35dMQVrHri6gotrQCtWrXitdde46WXXqJFixZ8/PHHTJw4scB53bt3x+Fw5JvL2qNHjwLHCvPII48wePBghg4dSufOnQkKCuKGG27Ie95qtTJnzhw2bNhAixYtePjhh3nllfwrF/n4+DB1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\n"
          },
          "metadata": {}
        }
      ]
    }
  ]
}